#include <string.h> 
#include <stdio.h>
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>

#include "rngs.h"
#include "dominion.h" 
#include "dominion_helpers.h"

#define TESTS 10000

int main (int argc, char *argv[])
{
	int i;
	int j;
	int p;
	int whoseTurn;
	int seed;
	int numPlayers;
	int handCount;
	int numActions;
	int bonus;
	int deckCount;
	int discardCount;
	int numBuys;
	int coins;
	int playedCardCount;
	int phase;
	int outpostPlayed;
	int outpostTurn;
	int cardPosition;
	int firstTreasurePosition;
	int secondTreasurePosition;
	int randomTreasure;
	int randomNum;
	int numFails = 0;
	int numCoins;
	int totalHand;
	int totalHandAfter; 
	
	int playerHandCount[4] = {0, 0, 0, 0};
	        
	int k[10] = {adventurer, council_room, feast, gardens, mine
	             , remodel, smithy, village, baron, great_hall};
	struct gameState G;

	srand(time(NULL));

	for (i = 0; i < TESTS; i++) {
		//initialize the game 
		seed = rand() % 100000000 + 1; //seed must be positive less then 9 dig 
		numPlayers = rand() % 3 + 2; // 2-4
		memset(&G, 23, sizeof(struct gameState));
		initializeGame(numPlayers, k, seed, &G);

		//setup for each player
		for (p = 0; p < numPlayers; p++) {
			G.handCount[p] = rand() % MAX_HAND;
			for (j = 0; j < G.handCount[p]; j++)
				G.hand[p][j] = k[(rand() % 10)]; //rand card 0-10 from k[] 
			G.deckCount[p] = rand() % MAX_DECK + 4; //needed for council_room
			for (j = 0; j < G.deckCount[p]; j++)
				G.deck[p][j] = k[(rand() % 10)]; //rand card 0-10 from k[]  
			G.discardCount[p] = rand() % MAX_DECK; 
			for (j = 0; j < G.discardCount[p]; j++)
				G.discard[p][j] = k[(rand() % 10)]; //rand card 0-10 from k[]  
                
		}

		//current player setup
		whoseTurn = rand() % numPlayers;
		G.whoseTurn = whoseTurn;
		numActions = rand() % 10 + 1; //needs to be at least one
		G.numActions = numActions;
		numBuys = rand() % 10 + 1; //needs to be at least one
		G.numBuys = numBuys;
		coins = rand() % 10;
		G.coins = coins; 
                
		handCount = G.handCount[whoseTurn];
		deckCount = G.deckCount[whoseTurn];
		discardCount = G.discardCount[whoseTurn];

		//unimplemented: phase, outpost, supply, embargo
		//(will possibly need for future cards)

		G.playedCardCount = rand() % MAX_DECK;
		for (j = 0; j < G.playedCardCount; j++)
			G.playedCards[j] = k[(rand() % 10)]; //rand card 0-10

		
		//insert card into hand
		cardPosition = 0; //always insert at start of hand
		G.hand[whoseTurn][cardPosition] = council_room; //change for different

		//get num of cards in all hands
		totalHand = 0;
		for (p = 0; p < numPlayers; p++) {
			totalHand = totalHand + G.handCount[p];
			playerHandCount[p] = G.handCount[p];
			//printf("DEBUG: G.handCount[%d]:%d\n", p, G.handCount[p]);
		}
		totalHand = totalHand - G.handCount[whoseTurn];
              
		//playcard
		if (cardEffect(council_room, 0, 0, 0, &G, cardPosition, NULL) == -1) {
			printf("FAIL: cardEffect() returned a failure\n");
			numFails++;
			printf("FAIL STATE: Seed:%d numPlayers:%d whoseTurn:%d handCount:%d deckCount:%d cardPosition:%d\n", seed, numPlayers, whoseTurn, handCount, deckCount, cardPosition);
		}

		//test if you have 3 extra cards   
		if (G.handCount[whoseTurn] == (handCount + 3)) {
			//printf("PASS: Correct number of cards in hand\n");
		}
		else {
			printf("FAIL: Incorrect number of cards in hand\n");
			numFails++;
			printf("FAIL STATE: Seed:%d numPlayers:%d whoseTurn:%d handCount:%d deckCount:%d cardPosition:%d\n", seed, numPlayers, whoseTurn, handCount, deckCount, cardPosition);
		}


		//get num of cards in all hands                                      
		totalHandAfter = 0;
		for (p = 0; p < numPlayers; p++) {
			totalHandAfter = totalHandAfter + G.handCount[p];
		}
		totalHandAfter = totalHandAfter - G.handCount[whoseTurn];
		
		//test if everyone else got 1 extra card
		if (totalHandAfter == (totalHand + (numPlayers - 1))) {
			//printf("PASS: Correct number of cards in hand\n");               
		}
		else {
			printf("FAIL: Incorrect number of cards in other players hand\n");
			numFails++;
			printf("FAIL STATE: Seed:%d numPlayers:%d whoseTurn:%d handCount:%d deckCount:%d cardPosition:%d\n", 
			       seed, numPlayers, whoseTurn, handCount, 
			       deckCount, cardPosition);
			printf("DEBUG: totalHand:%d totalHandAfter:%d\n", 
			       totalHand, totalHandAfter);
			for (p = 0; p < numPlayers; p++) {
				printf("DEBUG: playerHandCount[%d]:%d\n", 
				       p, playerHandCount[p]);
				printf("DEBUG: G.handCount[%d]:%d\n", p, G.handCount[p]);
			}
		}

		//test you have more buys 
		if (G.numBuys == (numBuys + 1)) {
			//printf("PASS: Buys correctly increased\n");
		}
		else {
			printf("FAIL: Buys did not increase\n");
			numFails++;
			printf("FAIL STATE: Seed:%d numPlayers:%d whoseTurn:%d handCount:%d deckCount:%d cardPosition:%d\n", seed, numPlayers, whoseTurn, handCount, deckCount, cardPosition);
		}
	}

	if (numFails == 0)
		printf("ALL TESTS PASSED\n");
	else {
		printf("%d TESTS FAILED\n", numFails);
	}

	return 0;
}
